package net.asrsmid.connection;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import net.asrsmid.config.AsApplication;
import net.asrsmid.config.AsRsConfig;
import net.asrsmid.config.RsApplication;
import net.asrsmid.connection.as.AsOlapConnection;
import net.asrsmid.connection.as.AsOlapConnectionFactory;
import net.asrsmid.connection.rs.RsWebserviceProxy;
import net.asrsmid.connection.rs.RsWebserviceProxyFactory;


/**
 * public class AsRsApplicationPool<br><br>
 * @author Chen WANG
 * @since 05 May 2011
 */
public class AsRsApplicationPool {

	private Map<String, AsRsConnectionPool> asPools;
	private Map<String, AsOlapConnectionFactory> asFactories;
	
	private Map<String, AsRsConnectionPool> rsPools;
	private Map<String, RsWebserviceProxyFactory> rsFactories;
	
	private AsRsConfig config;

	public AsRsApplicationPool(AsRsConfig asrsConfig) {
		this(asrsConfig, true);
	}
	
	/**
	 * @param asrsConfig
	 */
	public AsRsApplicationPool(AsRsConfig asrsConfig, boolean init) {
		// conserve AsRsConfig object
		config = asrsConfig;
		
		// initialize factories and pools
		asPools = new HashMap<String, AsRsConnectionPool>();
		asFactories = new HashMap<String, AsOlapConnectionFactory>();
		rsPools = new HashMap<String, AsRsConnectionPool>();
		rsFactories = new HashMap<String, RsWebserviceProxyFactory>();
		
		// as part
		Collection<AsApplication> asApps = asrsConfig.getAsApplications();
		for (AsApplication asApp : asApps) {
			String appId = asApp.getAppId();
			
			AsOlapConnectionFactory asFac = new AsOlapConnectionFactory(asApp);
			AsRsConnectionPool asPool = new AsRsConnectionPool(asFac, appId);
			
			asPool.setMaxActive(asApp.getPoolMaxActive());
			asPool.setMinIdle(asApp.getPoolMaxIdle());
			asPool.setMaxIdle(asApp.getPoolMaxIdle());
			asPool.setMaxWait(asApp.getPoolMaxWait());
			
			asPools.put(appId, asPool);
			asFactories.put(appId, asFac);
			
			// initialize idle connections
			if (init) {
				int minIdle = asApp.getPoolMaxIdle();
				try {
					for (int i = 0; i < minIdle; i++) {
						asPool.addObject();
					}
				} catch (Exception e) {
					// initialization fails
					e.printStackTrace();
				}	
			}
		}

		// rs part
		Collection<RsApplication> rsApps = asrsConfig.getRsApplications();
		for (RsApplication rsApp : rsApps) {
			String appId = rsApp.getAppId();
			
			RsWebserviceProxyFactory rsFac = new RsWebserviceProxyFactory(rsApp);
			AsRsConnectionPool rsPool = new AsRsConnectionPool(rsFac, appId);
			
			rsPool.setMaxActive(rsApp.getPoolMaxActive());
			rsPool.setMinIdle(rsApp.getPoolMaxIdle());
			rsPool.setMaxIdle(rsApp.getPoolMaxIdle());
			rsPool.setMaxWait(rsApp.getPoolMaxWait());
			
			rsPools.put(appId, rsPool);
			rsFactories.put(appId, rsFac);
			
			// initialize idle connections
			if (init) {
				int minIdle = rsApp.getPoolMaxIdle();
				try {
					for (int i = 0; i < minIdle; i++) {
						rsPool.addObject();
					}
				} catch (Exception e) {
					// initialization fails
					e.printStackTrace();
				}	
			}
		}
	}

	/**
	 * @param appId
	 * @return
	 */
	public AsOlapConnection getAsOlapConnection(String appId) {
		AsOlapConnection conn = null;
		try {
			AsRsConnectionPool asPool = asPools.get(appId);
			conn = (AsOlapConnection) asPool.borrowObject();
			// conn.register(asPool);
		} catch (Exception e) {
			// error when borrowing connection from pool
			e.printStackTrace();
		}
		return conn;
	}

	/**
	 * @param appId
	 * @return
	 */
	public RsWebserviceProxy getRsWebserviceProxy(String appId) {
		RsWebserviceProxy conn = null;
		try {
			AsRsConnectionPool rsPool = rsPools.get(appId);
			conn = (RsWebserviceProxy) rsPool.borrowObject();
			// conn.register(rsPool);
		} catch (Exception e) {
			// error when borrowing connection from pool
			e.printStackTrace();
		}
		return conn;
	}
	
	/**
	 * Returns the AsRsConfig object used to construct the pool
	 * @return the AsRsConfig object
	 */
	public AsRsConfig getConfig() {
		return config;
	}
}